/*
 * File: $Id: mb.h,v 1.17 2006/12/07 22:10:34 wolti Exp $
 */

#ifndef _MB_H
#define _MB_H

#ifdef __cplusplus
PR_BEGIN_EXTERN_C
#endif

#include "mbproto.h"

/* Modbus
 * #include "mb.h"
 *
 * This module defines the interface for the application. It contains
 * the basic functions and types required to use the Modbus protocol stack.
 * A typical application will want to call eMBInit() first. If the device
 * is ready to answer network requests it must then call eMBEnable() to activate
 * the protocol stack. In the main loop the function eMBPoll() must be called
 * periodically. The time interval between pooling depends on the configured
 * Modbus timeout. If an RTOS is available a separate task should be created
 * and the task should always call the function eMBPoll().
 *
 * eMBInit( MB_RTU, 0x0A, 38400, MB_PAR_EVEN );		// Initialize protocol stack in RTU mode for a slave with address 10 = 0x0A
 * eMBEnable(  );									// Enable the Modbus Protocol Stack.
 * for( ;; ) {
 * 		// Call the main polling loop of the Modbus protocol stack.
 * 		eMBPoll(  );
 * 		...
 * }
 */

/* ----------------------- Type definitions ---------------------------------*/

/* Modbus serial transmission modes (RTU/ASCII).
 *
 * Modbus serial supports two transmission modes. Either ASCII or RTU. RTU
 * is faster but has more hardware requirements and requires a network with
 * a low jitter. ASCII is slower and more reliable on slower links (E.g. modems)
 */


/* If register should be written or read.
 * This value is passed to the callback functions which support either
 * reading or writing register values. Writing means that the application
 * registers should be updated and reading means that the modbus protocol
 * stack needs to know the current register values.
 * see eMBRegHoldingCB( ), eMBRegCoilsCB( ), eMBRegDiscreteCB( ) and eMBRegInputCB( ).
 */
typedef enum {
    MB_REG_READ,                /*!< Read register values and pass to protocol stack. */
    MB_REG_WRITE                /*!< Update register values. */
} eMBRegisterMode;



/* ----------------------- Function prototypes ------------------------------*/
/* Initialize the Modbus protocol stack.
 *
 * This functions initializes the ASCII or RTU module and calls the
 * init functions of the porting layer to prepare the hardware. Please
 * note that the receiver is still disabled and no Modbus frames are
 * processed until eMBEnable( ) has been called.
 *
 * eMode If ASCII or RTU mode should be used.
 * ucSlaveAddress The slave address. Only frames sent to this address or to the broadcast address are processed.
 * ulBaudRate The baudrate. E.g. 19200. Supported baudrates depend on the porting layer.
 * eParity Parity used for serial transmission.
 *
 * If no error occurs the function returns eMBErrorCode::MB_ENOERR.
 * The protocol is then in the disabled state and ready for activation
 * by calling eMBEnable( ). Otherwise one of the following error codes
 * is returned:
 * 		- eMBErrorCode::MB_EINVAL If the slave address was not valid. Valid slave addresses are in the range 1 - 247.
 * 		- eMBErrorCode::MB_EPORTERR IF the porting layer returned an error.
 */


/* Release resources used by the protocol stack.
 * This function disables the Modbus protocol stack and release all
 * hardware resources. It must only be called when the protocol stack
 * is disabled.
 *
 * Note all ports implement this function. A port which wants to get an callback must define the macro MB_PORT_HAS_CLOSE to 1.
 *
 * If the resources where released it return eMBErrorCode::MB_ENOERR.
 * If the protocol stack is not in the disabled state it returns eMBErrorCode::MB_EILLSTATE.
 */
eMBErrorCode MYLIBSECTION eMBClose( void );

/* Enable the Modbus protocol stack.
 * This function enables processing of Modbus frames. Enabling the protocol
 * stack is only possible if it is in the disabled state.
 *
 * If the protocol stack is now in the state enabled it returns eMBErrorCode::MB_ENOERR.
 * If it was not in the disabled state it return eMBErrorCode::MB_EILLSTATE.
 */
eMBErrorCode  MYLIBSECTION  eMBEnable( void );

/* Disable the Modbus protocol stack.
 * This function disables processing of Modbus frames.
 *
 * If the protocol stack has been disabled it returns eMBErrorCode::MB_ENOERR.
 * If it was not in the enabled state it returns eMBErrorCode::MB_EILLSTATE.
 */
eMBErrorCode MYLIBSECTION   eMBDisable( void );

/* The main pooling loop of the Modbus protocol stack.
 *
 * This function must be called periodically. The timer interval required
 * is given by the application dependent Modbus slave timeout. Internally the
 * function calls xMBPortEventGet() and waits for an event from the receiver or
 * transmitter state machines.
 *
 * If the protocol stack is not in the enabled state the function returns eMBErrorCode::MB_EILLSTATE.
 * Otherwise it returns eMBErrorCode::MB_ENOERR.
 */
eMBErrorCode  MYLIBSECTION  eMBPoll( void );

/* Configure the slave id of the device.
 *
 * This function should be called when the Modbus function Report Slave ID
 * is enabled ( By defining MB_FUNC_OTHER_REP_SLAVEID_ENABLED in mbconfig.h ).
 *
 * ucSlaveID Values is returned in the Slave ID byte of the Report Slave ID response.
 * xIsRunning If TRUE the Run Indicator Status byte is set to 0xFF. otherwise the Run Indicator Status is 0x00.
 * pucAdditional Values which should be returned in the Additional bytes of the Report Slave ID response.
 * usAdditionalLen Length of the buffer pucAdditonal.
 *
 * If the static buffer defined by MB_FUNC_OTHER_REP_SLAVEID_BUF in mbconfig.h is to small it returns eMBErrorCode::MB_ENORES.
 * Otherwise it returns eMBErrorCode::MB_ENOERR.
 */
eMBErrorCode  MYLIBSECTION  eMBSetSlaveID(UCHAR 			ucSlaveID,
											BOOL			xIsRunning,
											UCHAR	const	*pucAdditional,
											USHORT			usAdditionalLen );

/* Registers a callback handler for a given function code.
 *
 * This function registers a new callback handler for a given function code.
 * The callback handler supplied is responsible for interpreting the Modbus PDU and
 * the creation of an appropriate response. In case of an error it should return
 * one of the possible Modbus exceptions which results in a Modbus exception frame
 * sent by the protocol stack.
 *
 * ucFunctionCode The Modbus function code for which this handler should be registers. Valid function codes are in the range 1 to 127.
 * pxHandler The function handler which should be called in case such a frame is received.
 * If NULL a previously registered function handler for this function code is removed.
 *
 * eMBErrorCode::MB_ENOERR if the handler has been installed.
 * If no more resources are available it returns eMBErrorCode::MB_ENORES.
 * In this case the values in mbconfig.h should be adjusted. If the argument was not valid it returns eMBErrorCode::MB_EINVAL.
 */
eMBErrorCode  MYLIBSECTION  eMBRegisterCB(	UCHAR				ucFunctionCode,
											pxMBFunctionHandler	pxHandler		);

/* ----------------------- Callback -----------------------------------------*/

/* Modbus Registers
 * #include "mb.h"
 *
 * The protocol stack does not internally allocate any memory for the
 * registers. This makes the protocol stack very small and also usable on
 * low end targets. In addition the values don't have to be in the memory
 * and could for example be stored in a flash.
 * Whenever the protocol stack requires a value it calls one of the callback
 * function with the register address and the number of registers to read
 * as an argument. The application should then read the actual register values
 * (for example the ADC voltage) and should store the result in the supplied
 * buffer.
 * If the protocol stack wants to update a register value because a write
 * register function was received a buffer with the new register values is
 * passed to the callback function. The function should then use these values
 * to update the application register values.
 */

/* Callback function used if a Holding Register value is
 * read or written by the protocol stack. The starting register address
 * is given by usAddress and the last register is given by usAddress + usNRegs - 1.
 *
 * pucRegBuffer If the application registers values should be updated the
 * buffer points to the new registers values. If the protocol stack needs
 * to now the current values the callback function should write them into this buffer.
 *
 * usAddress The starting address of the register.
 * usNRegs Number of registers to read or write.
 * eMode If eMBRegisterMode::MB_REG_WRITE the application register values should be updated from the values in the buffer.
 *
 * For example this would be the case when the Modbus master has issued an WRITE SINGLE REGISTER command.
 * If the value eMBRegisterMode::MB_REG_READ the application should copy the current values into the buffer pucRegBuffer.
 *
 * The function must return one of the following error codes:
 * 		-	eMBErrorCode::MB_ENOERR		If no error occurred. In this case a normal Modbus response is sent.
 * 		-	eMBErrorCode::MB_ENOREG		If the application can not supply values for registers within this range. In this case a
 * 										ILLEGAL DATA ADDRESS exception frame is sent as a response.
 * 		-	eMBErrorCode::MB_ETIMEDOUT	If the requested register block is currently not available and the application dependent response
 * 										timeout would be violated. In this case a SLAVE DEVICE BUSY exception is sent as a response.
 * 		-	eMBErrorCode::MB_EIO		If an unrecoverable error occurred. In this case a SLAVE DEVICE FAILURE exception is sent as a response.
 */
eMBErrorCode MYLIBSECTION   eMBRegHoldingCB(	UCHAR*				pucRegBuffer,
												USHORT				usAddress,
												USHORT				usNRegs,
												eMBRegisterMode		eMode		);



#ifdef __cplusplus
PR_END_EXTERN_C
#endif
#endif
